﻿using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Xml.Linq;
using SuperSimpleWebshop.Common;
using SuperSimpleWebshop.Domain;
using SuperSimpleWebshop.Domain.Helpers;
using SuperSimpleWebshop.Domain.Interfaces;
using umbraco;
using umbraco.BusinessLogic;
using umbraco.presentation.nodeFactory;
using System.Threading;

namespace SuperSimpleWebshop.Payment.MultiSafePay
{
    public class MultiSafePayPaymentRequestHandler : MultiSafePayPaymentBase, IPaymentRequestHandler
    {
        #region IPaymentRequestHandler Members
        public PaymentRequest CreatePaymentRequest(Order order)
        {
            try
            {
                var helper = new PaymentConfigHelper(order.OrderInfo.PaymentInfo.PaymentProviderNodeName);

                var paymentProvider = this.OrderRepository.GetAllPaymentProviders().Where(x => x.Name == order.OrderInfo.PaymentInfo.PaymentProviderNodeName).FirstOrDefault();

                #region build urls
                var baseUrl = string.Format("http://{0}", library.GetCurrentDomains(Node.GetCurrent().Id).FirstOrDefault().Name);
                baseUrl = baseUrl.Substring(0, baseUrl.LastIndexOf("/"));

                var oldUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
                var oldCulture = System.Threading.Thread.CurrentThread.CurrentCulture;

                var shopAliasNode = ShopAliasHelper.GetAllShopAlias().Where(x => x.Name.ToLower() == order.OrderInfo.ShopAlias.Alias.ToLower()).FirstOrDefault();

                Thread.CurrentThread.CurrentCulture = shopAliasNode.CultureInfo;
                Thread.CurrentThread.CurrentUICulture = shopAliasNode.CultureInfo;

                var nodeId = DomainHelper.GetNodeIdForDocument("sswsOrderProcessNode", library.GetDictionaryItem("PaymentConfirmation"), ShopAliasHelper.GetCurrentShopAlias());
                var cancelNodeId = DomainHelper.GetNodeIdForDocument("sswsOrderProcessNode", library.GetDictionaryItem("PaymentConfirmationFailed"), ShopAliasHelper.GetCurrentShopAlias());

                System.Threading.Thread.CurrentThread.CurrentUICulture = oldUICulture;
                System.Threading.Thread.CurrentThread.CurrentCulture = oldCulture;

                var returnUrl = string.Format("{0}{1}", baseUrl, library.NiceUrl(nodeId));
                var cancelUrl = string.Format("{0}{1}", baseUrl, library.NiceUrl(cancelNodeId));
                string reportUrl = string.Format("{0}{1}", baseUrl, library.NiceUrl(paymentProvider.Id));
                #endregion

                #region fill transactionrequest object
                TransactionRequest transactionRequest = new TransactionRequest();

                transactionRequest.AccountId = long.Parse(helper.Settings["accountId"]);
                transactionRequest.SiteId = long.Parse(helper.Settings["siteId"]);
                transactionRequest.SiteSecureId = long.Parse(helper.Settings["siteSecureId"]);

                // Notification URL
                transactionRequest.NotificationUrl = reportUrl;
                // Cancel URL    
                transactionRequest.CancelUrl = cancelUrl;
                // Redirect URL
                transactionRequest.RedirectUrl = returnUrl;

                transactionRequest.Locale = order.OrderInfo.CultureInfo.TwoLetterISOLanguageName + "_" + order.OrderInfo.CustomerInfo.CountryCode;
                transactionRequest.IPAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
                transactionRequest.ForwardedIP = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                transactionRequest.FirstName = order.CustomerFirstName;
                transactionRequest.LastName = order.CustomerLastName;
                transactionRequest.Country = order.OrderInfo.CustomerInfo.CountryCode;
                transactionRequest.Email = order.CustomerEmail;

                int amount = Convert.ToInt32(OrderHelper.GetTotalAmountUsingVATCheck() * 100);

                transactionRequest.TransactionId = order.UniqueId.ToString();
                transactionRequest.Currency = order.OrderInfo.ShopAlias.CurrencyCode;
                transactionRequest.Amount = amount;
                transactionRequest.Decription = order.OrderInfo.OrderNumber;
                transactionRequest.Gateway = order.OrderInfo.PaymentInfo.PaymentProviderMethodId;

                var stringToHash = amount.ToString() + transactionRequest.Currency + transactionRequest.AccountId.ToString() + transactionRequest.SiteId.ToString() + transactionRequest.TransactionId;

                transactionRequest.Signature = GetMd5Sum(stringToHash);
                #endregion

                string apiURL = string.Empty;

                if (helper.TestModeEnabled)
                {
                    apiURL = helper.Settings["testURL"];
                }
                else
                {
                    apiURL = helper.Settings["url"];
                }

                try
                {
                    var httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(apiURL);
                    httpWebRequest.Method = "POST";
                    httpWebRequest.ContentLength = Encoding.UTF8.GetByteCount(transactionRequest.GetXML());
                    httpWebRequest.ContentType = "application/x-www-form-urlencoded";

                    var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream());
                    streamWriter.Write(transactionRequest.GetXML());
                    streamWriter.Close();

                    var httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                    var streamReader = new StreamReader(httpWebResponse.GetResponseStream());

                    //<?xml version="1.0" encoding="UTF-8" ?>
                    //<redirecttransaction result="ok">
                    //  <transaction>
                    //      <id>4084044</id>
                    //      <payment_url>https://user.multisafepay.com/pay/?trans...</payment_url>
                    //  </transaction>
                    //</redirecttransaction>
                    var xmlDoc = XDocument.Parse(streamReader.ReadToEnd());

                    XElement transaction = null;
                    XElement paymentUrl = null;

                    try
                    {
                        transaction = xmlDoc.Root.Element("transaction");
                        paymentUrl = transaction.Element("payment_url");
                    }
                    catch (Exception ex)
                    {
                        Log.Add(LogTypes.Debug, 0, "Not the required information received from MultiSafePay: " + xmlDoc.ToString());
                    }

                    if (transaction != null && paymentUrl != null)
                    {
                        order.OrderInfo.PaymentInfo.PaymentParameterRenderMethod = PaymentParameterRenderMethod.Custom;
                        order.OrderInfo.PaymentInfo.PaymentURL = paymentUrl.Value;
                        order.OrderInfo.PaymentInfo.PaymentTransactionId = order.UniqueOrderId.ToString();
                    }
                }
                catch (Exception ex)
                {
                    Log.Add(LogTypes.Error, 0, "multisafepay create payment request error: " + ex.ToString());
                }
            }
            catch (Exception ex)
            {
                Log.Add(LogTypes.Error, 0, "MultiSafePayPaymentRequestHandler.CreatePaymentRequest: " + ex.ToString());
            }

            return null;
        }
        #endregion

        // Create an md5 sum string of this string
        public static string GetMd5Sum(string str)
        {
            MD5CryptoServiceProvider x = new MD5CryptoServiceProvider();

            byte[] data = Encoding.ASCII.GetBytes(str);

            data = x.ComputeHash(data);

            return BitConverter.ToString(data).Replace("-", "").ToLower();
        }
    }
}
